package com.zrh.jsd.service.studydemo.java_base.string;

import java.lang.reflect.Field;

/*
 * String 是不可变的，因为String底层是final char[]
 * 不可变指的是String指向的栈地址不可变
 *
 * */
public class StringTest {
    public static void main(String[] args) throws NoSuchFieldException, ClassNotFoundException, IllegalAccessException {
        final char[] a = {'你', '好'};
        char[] b = {'你', '坏'};
//        修改数组指向另一个内存地址。会报错，提示a是final
//        a = b;
        a[0] = '他'; //修改a[0]的值
        System.out.println(a);

        // m只是"abc"这个对象的引用，不是对象本身。m通过指向"abc"在字符串常量池的地址获取到"abc","abc"在字符串常量池的地址是不可变的。
        String m = "abc";
        System.out.println(m + "-" + m.hashCode()); // "abc"的地址是96354
        m = "hgg";   //
        System.out.println(m + "-" + m.hashCode()); // 重新赋值以后变为"103240"
        change(m);
        System.out.println(m + "-" + m.hashCode()); // 通过反射修改内容后的地址仍然是"103240"
        String n = "bbb";
        System.out.println(n + "-" + n.hashCode()); // "bbb"是新的字符串，所以jvm给其分配新的内存地址
        String p = "hgg";
        System.out.println(p + "-" + p.hashCode()); // p指向的仍然是"hgg"的地址，所以其对应的内容已经被改成了"bbb"
        /*
        * 输出结果：
        *   他好
            abc-96354
            hgg-103240
            bbb-103240
            bbb-97314
            bbb-103240
        * */
    }

    public static void change(String a) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        // 利用凡是获取String中的value数组
        Class<?> clazz = Class.forName("java.lang.String");
        Field field = clazz.getDeclaredField("value");
        field.setAccessible(true);
        char[] value = (char[]) field.get(a);

        //直接修改value数组中的值
        for (int i = 0; i < value.length; i++) {
            value[i] = 'b';
        }
    }
}
